using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace EPPlayer
{
    public class ValueAttribute : Attribute, INotifyPropertyChanged, IAttachableAttribute
    {
        private int RawValue;

        /// <summary>
        /// Things that change me
        /// </summary>
        protected List<IFilter> Filters = new List<IFilter>();
        /// <summary>
        /// Dependent attributes (who to notify if my value changes)
        /// </summary>
        internal List<ValueAttribute> DownstreamAttributes = new List<ValueAttribute>();

        internal ValueAttribute(string Name, string Color, int Value, string Description = null)
            : base(Name, Color, Description)
        {
            this.RawValue = Value;
        }
        public int rawValue
        {
            get { return this.RawValue; }
            set
            {
                if (this.RawValue != value)
                {
                    this.RawValue = value;
                    NotifyPropertyChanged();
                    NotifyPropertyChanged("cookedValue");
                    foreach (ValueAttribute Dependent in DownstreamAttributes)
                    {
                        // todo: work the dependency graph!
                    }
                }
            }
        }
        public int cookedValue
        {
            get
            {
                int Result = this.RawValue;
                foreach (AttributeFilter Filter in Filters)
                {
                    Result = Filter.FilteredValue(Result);
                }
                return Result;
            }
        }
        public List<string> cookedValueText
        {
            get
            {
                List<string> Log = new List<string>();
                int Result = this.RawValue;
                int Previous = Result;
                Log.Add(string.Format("Initial value of {0}: {1}", this.Name, Result.ToString()));
                
                foreach (AttributeFilter Filter in Filters)
                {
                    Result = Filter.FilteredValue(Result);
                    Log.Add(string.Format("Filter {0}/{1}: {2} ({3})", Filter.color, Filter.name, Result - Previous, Filter.description));
                    Previous = Result;
                }
                return Log;
            }
        }
        internal void AddFilter(IFilter Filter)
        {
            this.Filters.Add(Filter);
            NotifyPropertyChanged("cookedValue");
        }

        internal void RemoveFilter(IFilter Filter)
        {
            this.Filters.Remove(Filter);
            NotifyPropertyChanged("cookedValue");
        }

        internal void AddDependent(Attribute Dependent)
        {
            this.DownstreamAttributes.Add(Dependent as ValueAttribute);
        }

        internal void RemoveDependent(Attribute Dependent)
        {
            this.DownstreamAttributes.Remove(Dependent as ValueAttribute);
        }

        public void OnAttach(Entity Entity)
        {
        }
        public void OnDetach(Entity Entity)
        {
            this.RawValue = 0;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}